package util;

import indexes.PlayerName;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
import java.util.regex.Pattern;

public class CSVFileParser
{
    //begin column order data
    final private static short NUM_COLUMNS = 15;
    final private static short PLAYER_ID = 0;
    final private static short BIRTH_YEAR = 1;
    final private static short BIRTH_PLACE = 2;
    final private static short BIRTH_COUNTRY = 3;
    final private static short DEATH_YEAR = 4;
    final private static short DEATH_PLACE = 5;
    final private static short DEATH_COUNTRY = 6;
    final private static short FIRST_NAME = 7;
    final private static short LAST_NAME = 8;
    final private static short WEIGHT = 9;
    final private static short HEIGHT = 10;
    final private static short BATS = 11;
    final private static short THROWS = 12;
    final private static short BEGIN = 13;
    final private static short END = 14;
    //end column order data
    
    private Scanner lineScanner;
    
    /**
     * Lines are delimited by a newline.
     */
    private static final String LINE_DELIMETER = "\n";
    /**
     * Tokens are delimited by a tab.
     */
    private static final Pattern TOKEN_DELIMETER = Pattern.compile(",");
    
    /**
     * Constructor:
     * create a scanner for the file,
     * set the line delimeter.
     * @param fileName
     * @throws FileNotFoundException 
     */
    public CSVFileParser(String fileName) throws FileNotFoundException
    {
        lineScanner = new Scanner(new File(fileName));
        lineScanner.useDelimiter(LINE_DELIMETER);
    }
    
    public void close()
    {
        lineScanner.close();
    }
    
    /**
     * Checks for more records (lines)
     * @return true if more lines exist.
     */
    public boolean hasNext()
    {
        return lineScanner.hasNext();
    }
    
    /**
     * Parses the next line and returns a record.
     * @return A record with the name, id, and line text.
     */
    public Record nextRecord()
    {
        String line = lineScanner.next();
        String[] values = parseColumns(line);
        String id = values[PLAYER_ID];
        String name = values[LAST_NAME] + ", " + values[FIRST_NAME];
        return new Record(id, name, line);
    }
    
    /**
     * Parses a line into an array of values corresponding
     * to their order in the record.
     * @param line line to parse
     * @return an array of values
     */
    private static String[] parseColumns(String line)
    {
        Scanner tokenScanner = new Scanner(line);
        tokenScanner.useDelimiter(TOKEN_DELIMETER);
        String[] values = new String[NUM_COLUMNS];
        for (int i = 0; i < NUM_COLUMNS; i++)
        {
            values[i] = tokenScanner.next();
        }
        return values;
    }
    
    /**
     * Creates a player object from a line of text
     * @param line
     * @return
     */
    public static Player createPlayer(String line)
    {
        return createPlayer(parseColumns(line));
    }
    
    /**
     * Creates a player from the given values.
     * @param values array of values to create player from - should
     * correspond to the column numbers.
     * @return a player object encapsulating these values.
     */
    public static Player createPlayer(String[] values)
    {
        String playerId = values[PLAYER_ID];
        String birthYear = values[BIRTH_YEAR];
        String birthPlace = values[BIRTH_PLACE];
        String birthCountry = values[BIRTH_COUNTRY];
        String deathYear = values[DEATH_YEAR];
        String deathPlace = values[DEATH_PLACE];
        String deathCountry = values[DEATH_COUNTRY];
        String firstName = values[FIRST_NAME];
        String lastName = values[LAST_NAME];
        int weight;
        if (values[WEIGHT].isEmpty())
        {
            weight = -999;
        }
        else
        {
            weight = Integer.parseInt(values[WEIGHT]);
        }
        int height;
        if (values[HEIGHT].isEmpty())
        {
            height = -999;
        }
        else
        {
            height = Integer.parseInt(values[HEIGHT]);
        }
        char bats;
        if (values[BATS].isEmpty())
        {
            bats = 'Z';
        }
        else
        {
            bats = values[BATS].charAt(0);
        }
        char throwing;
        if (values[THROWS].isEmpty())
        {
            throwing = 'Z';
        }
        else
        {
            throwing = values[THROWS].charAt(0);
        }
        String beginDate = values[BEGIN];
        String endDate = values[END];
        return new Player(playerId, birthYear, birthPlace, birthCountry,
            deathYear, deathPlace, deathCountry, firstName, lastName, 
            weight, height, bats, throwing, beginDate, endDate);
    }
}
